package ua.org.groovy.gs.botworld;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import groovy.lang.Closure;

import ua.org.groovy.gs.botworld.event.CollisionEvent;
import ua.org.groovy.gs.botworld.event.Event;
import ua.org.groovy.gs.botworld.event.TickEvent;
import ua.org.groovy.gs.core.Agent;

public class Bot extends Agent {
	
	private final static int TICK_TIMEOUT = 1000;

	private int tickTimer = 0;

	public final static int MOVING_LEFT = 1;
	public final static int MOVING_RIGHT = 2;
	public final static int MOVING_UP = 3;
	public final static int MOVING_DOWN = 4;
	public final static int STANDING = 5;

	private int state = STANDING;
		
	private int posX = 10;
	
	private int posY = 10;
	
	private float radius = 10;

	private final static int MIN_RADIUS = 10;

	private final static int MAX_RADIUS = 17;
	
	private boolean isRadiusIncreasing;

	private final static int BALOON_TIMEOUT = 2000;
	
	private int baloonTimer = 0;
	
	private Baloon baloon;
	
	/* Public event handling fields */
	public Closure onTick;
	public Closure onCollision;
	

	public Bot() {
		super ();
	}
	
	public void moveLeft() {
		state = MOVING_LEFT;
	}

	public void moveRight() {
		state = MOVING_RIGHT;
	}
	
	public void moveUp() {
		state = MOVING_UP;
	}
	
	public void moveDown() {
		state = MOVING_DOWN;
	}
	
	public void stop() {
		state = STANDING;
	}

	public void sayOuch() {
		if (baloon == null)
			baloon = new Baloon(0, 0);
		baloon.setPosition(posX, posY - 30);
		this.baloonTimer = BALOON_TIMEOUT;
	}

	private void updateRadius() {
		if (radius < MIN_RADIUS)
			isRadiusIncreasing = true;
		
		if (radius > MAX_RADIUS)
			isRadiusIncreasing = false;
		
		radius += isRadiusIncreasing ? 0.1f : -0.1f;
	}

	private void updateMovement() {
		synchronized (this) {
			int newPosX = posX;
			int newPosY = posY;
			if (this.state == STANDING)
				return;
			
			switch (state) {
				case MOVING_LEFT:
					newPosX--;
					break;
				case MOVING_RIGHT:
					newPosX++;
					break;
				case MOVING_UP:
					newPosY--;
					break;
				case MOVING_DOWN:
					newPosY++;
					break;
	
				default:
					break;
			}
			
			Rectangle rect = new Rectangle(newPosX - 9, newPosY - 9, 18, 18);
			Rectangle obstacle = new Rectangle(130, 70, 40, 10);
			
			if(rect.intersects(obstacle)) {
				state = STANDING;
				fireEvent(new CollisionEvent());
			} else {
				this.posX = newPosX;
				this.posY = newPosY;
			}			
		}
	}

	private void updateBaloon(int deltaMillis) {
		if (baloonTimer > 0) {
			baloonTimer -= deltaMillis;
		}
	}
	
	public void update(int deltaMillis) {
		tickTimer -= deltaMillis;
		if (tickTimer < 0) {
			tickTimer = TICK_TIMEOUT;
			fireEvent(TickEvent.getInstance());
		}
		
		updateMovement();
		updateRadius();
		updateBaloon(deltaMillis);
	}
	
	
	public void draw(Graphics2D g) {
		g.setColor(new Color(0x888888));
		g.fillOval(
				posX - (int)radius/2, 
				posY - (int)radius/2, 
				(int)radius, 
				(int)radius);
		
		if (baloonTimer > 0 && baloon != null) {
			baloon.setPosition(posX - 3, posY - 35);
			baloon.draw(g);
		}	
	}
}
